#ifndef __MTEXTURE_STATE_H__
#define __MTEXTURE_STATE_H__

#include <string>
#include "Matrix.h"
#include "GLTexture.h"
#include "MBlendMode.h"

class CMPass;

class CMTextureState
{
public:	
	
	enum _TextureFilterType
	{
		// The filter used when shrinking a texture
		TEX_FILTERTYPE_MIN ,

		// The filter used when magnifiying a texture
		TEX_FILTERTYPE_MAG ,

		// The filter used when determining the mipmap
		TEX_FILTERTYPE_MIP
	};
	typedef enum _TextureFilterType TextureFilterType;

	// Filtering options for textures / mipmaps.
	enum _TextureFilterOptions
	{
		/// No filtering, used for FILT_MIP to turn off mipmapping
		TEX_FILTEROPTION_NONE,
		/// Use the closest pixel
		TEX_FILTEROPTION_POINT,
		/// Average of a 2x2 pixel area, denotes bilinear for MIN and MAG, trilinear for MIP
		TEX_FILTEROPTION_LINEAR,
		/// Similar to TEX_FILTEROPTION_LINEAR, but compensates for the angle of the texture plane
		TEX_FILTEROPTION_ANISOTROPIC
	};
	typedef enum _TextureFilterOptions TextureFilterOptions;

	// Texture addressing modes
	enum _TextureAddressingMode
	{
		// Texture wraps at values over 1.0
		TEX_ADDRESS_WRAP,

		// Texture mirrors (flips) at joins over 1.0
		TEX_ADDRESS_MIRROR,

		// Texture clamps at 1.0
		TEX_ADDRESS_CLAMP,

		/// Texture coordinates outside the range [0.0, 1.0] are set to the border colour
		TEX_ADDRESS_BORDER
	};
	typedef enum _TextureAddressingMode TextureAddressingMode;

public:

	// constructor
	CMTextureState( CMPass* pParent );
	CMTextureState( CMPass* pParent , const CMTextureState& rhs );
	CMTextureState( CMPass* pParent , const std::string& strTextureName , unsigned int uiTexCoordSet = 0 );

	// destructor
	~CMTextureState( void );

	// copy
	CMTextureState& operator=( const CMTextureState& rhs );

	// Internal method for loading this object as part of Material::Load
	void Load( void );

	// Internal method for unloading this object as part of Material::Unload
	void Unload( void );

	// Get the name of current texture image for this layer.
	// Gets the name of the texture associated with a frame number.
	const std::string& GetTextureName( unsigned int uiNumOfFrame = 0 ) const;

	// Changes the active frame in an animated or multi-image texture.
	void SetCurrentFrame( unsigned int uiNumOfFrame );

	// Gets the active frame in an animated or multi-image texture layer.
	unsigned int GetCurrentFrame( void ) const;

	// Sets this texture layer to use a single texture, given the name of the texture to use on this layer.
	void SetTextureName( const std::string& strName , GLTexture::TextureType eType = GLTexture::TEX_TYPE_2D ,  int iMipmaps = -1 );

	// Sets the index of the set of texture co-ords this layer uses.
	void SetTextureCoordSet( unsigned int uiTexCoordSet );

	// Gets the index of the set of texture co-ords this layer uses.
	unsigned int GetTextureCoordSet( void ) const;

	// Sets a matrix used to transform any texture coordinates on this layer.
	void SetTextureTransform( const mat4& mTransform );

	// Gets the current texture transformation matrix.
	const mat4& GetTextureTransform( void ) const;

	//
	void RecalculateTextureMatrix( void ) const;

	// Gets the texture addressing mode, i.e. what happens at uv values above 1.0.
	TextureAddressingMode GetTextureAddressingMode( void ) const;

	// Sets the texture addressing mode, i.e. what happens at uv values above 1.0.
	void SetTextureAddressingMode( TextureAddressingMode eTexAddressMode );

	// Set a single filtering option on this texture unit. 
	void SetTextureFiltering( TextureFilterType eFilterType , TextureFilterOptions eOption );

	// Set a the detailed filtering options on this texture unit. 
	void SetTextureFiltering( TextureFilterOptions eMinFilterOption , TextureFilterOptions eMagFilterOption , TextureFilterOptions eMipFilterOption );

	// Get the texture filtering for the given type
	TextureFilterOptions GetTextureFiltering( TextureFilterType eFilterType ) const;

	// Sets the anisotropy level to be used for this texture level.
	void SetTextureAnisotropy( UINT32 uiMaxAnisotropy );

	// get this layer texture anisotropy level
	UINT32 GetTextureAnisotropy( void ) const;

	// Get multitexturing color blending mode.
	const CMBlendMode& GetColorBlendMode( void ) const;

	// Determines how this texture layer is combined with the one below it (or the diffuse colour of the geometry if this is layer 0).
	void SetColorOperation( BlendOperation BlendOp );
	void SetColorOperation( const BlendOperationEx BlendOp , BlendSource eSource1 = BS_TEXTURE , BlendSource eSource2 = BS_CURRENT , const CMColor& ColorArg1 = CMColor::WHITE , const CMColor& ColorArg2 = CMColor::WHITE , float fManualBlend = 0.0f );

	// Get multitexturing alpha blending mode.
	const CMBlendMode& GetAlphaBlendMode( void ) const;

	// Sets the alpha operation to be applied to this texture.
	void SetAlphaOperation( BlendOperationEx BlendOp , BlendSource eSource1 = BS_TEXTURE , BlendSource eSource2 = BS_CURRENT , float fAlphaArg1 = 1.0f , float fAlphaArg2 = 1.0f , float fManualBlend = 0.0f );

	protected:

	// Sets default parameters
	void SetDefaultParameters( void );

	//
	// attribute 
	//

	protected:

		// parent
		CMPass* m_pParentPass;

		// texture type
		GLTexture::TextureType m_eTextureType; 

		//
		std::vector<std::string> m_Frames;

		std::vector<TexturePtr>  m_Textures;

		// The current animation frame.
		unsigned int m_uiCurrentFrame;

		// Duration of animation in seconds
		float m_fAnimationDuration;            

		// number of mipmaps
		int  m_iTextureSrcMipmaps;

		unsigned int  m_uiTextureCoordSetIndex;

		// texture addressing mode
		TextureAddressingMode m_eAddressMode;

		bool m_bIsDefaultFilter;

		// Texture filtering - minification
		TextureFilterOptions m_eMinFilter;

		// Texture filtering - magnification
		TextureFilterOptions m_eMagFilter;

		// Texture filtering - mipmapping
		TextureFilterOptions m_eMipFilter;

		// Texture anisotropy
		unsigned int  m_uiAnisotropy;

		// TextureFilterMode __eFilterMode;

		CMBlendMode m_ColorBlendMode;
		CMBlendMode m_AlphaBlendMode;

		mutable bool  m_bRecalculateTextureMatrix;
		mutable mat4  mTextureMatrix;
};

#endif 